package com.cinema.dao.impl;

import com.cinema.dao.ScheduleDao;
import com.cinema.model.Schedule;
import com.cinema.model.CinemaHall;
import com.cinema.util.SimpleFileUtil;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 排片数据访问实现类
 */
public class ScheduleDaoImpl implements ScheduleDao {
    private static final String SCHEDULE_DATA_FILE = "schedules.txt";
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private List<Schedule> schedules;

    public ScheduleDaoImpl() {
        loadSchedules();
    }

    private void loadSchedules() {
        schedules = new ArrayList<>();
        List<String> lines = SimpleFileUtil.readLines(SCHEDULE_DATA_FILE);
        for (String line : lines) {
            if (line.trim().isEmpty()) continue;
            Schedule schedule = parseScheduleFromLine(line);
            if (schedule != null) {
                schedules.add(schedule);
            }
        }
    }

    private void saveSchedules() {
        List<String> lines = new ArrayList<>();
        for (Schedule schedule : schedules) {
            lines.add(scheduleToLine(schedule));
        }
        SimpleFileUtil.writeLines(SCHEDULE_DATA_FILE, lines);
    }

    private Schedule parseScheduleFromLine(String line) {
        try {
            String[] parts = line.split("\\|");
            if (parts.length >= 6) {
                Schedule schedule = new Schedule();
                schedule.setScheduleId(parts[0]);
                schedule.setMovieId(parts[1]);
                schedule.setHallId(parts[2]);
                schedule.setShowTime(LocalDateTime.parse(parts[3], DATE_FORMATTER));
                schedule.setPrice(Double.parseDouble(parts[4]));
                schedule.setTotalSeats(Integer.parseInt(parts[5]));
                if (parts.length > 6) {
                    schedule.setAvailableSeats(Integer.parseInt(parts[6]));
                } else {
                    schedule.setAvailableSeats(schedule.getTotalSeats());
                }
                // 加载已占用座位信息
                if (parts.length > 7) {
                    schedule.setOccupiedSeats(parts[7]);
                } else {
                    schedule.setOccupiedSeats("");
                }
                // 根据放映厅ID获取正确的座位配置
                CinemaHall hall = CinemaHall.getHallById(schedule.getHallId());
                if (hall != null) {
                    schedule.initializeSeatStatus(hall.getRows(), hall.getSeatsPerRow());
                } else {
                    // 如果找不到放映厅，使用默认配置
                    schedule.initializeSeatStatus(10, 12);
                }
                return schedule;
            }
        } catch (Exception e) {
            // 跳过无效行
        }
        return null;
    }

    private String scheduleToLine(Schedule schedule) {
        return schedule.getScheduleId() + "|" + 
               schedule.getMovieId() + "|" + 
               schedule.getHallId() + "|" + 
               schedule.getShowTime().format(DATE_FORMATTER) + "|" + 
               schedule.getPrice() + "|" + 
               schedule.getTotalSeats() + "|" + 
               schedule.getAvailableSeats() + "|" + 
               (schedule.getOccupiedSeats() != null ? schedule.getOccupiedSeats() : "");
    }

    @Override
    public boolean save(Schedule schedule) {
        if (schedule == null || existsById(schedule.getScheduleId())) {
            return false;
        }
        
        schedules.add(schedule);
        saveSchedules();
        return true;
    }

    @Override
    public Optional<Schedule> findById(String scheduleId) {
        return schedules.stream()
                .filter(schedule -> scheduleId.equals(schedule.getScheduleId()))
                .findFirst();
    }

    @Override
    public List<Schedule> findAll() {
        return new ArrayList<>(schedules);
    }

    @Override
    public List<Schedule> findByMovieId(String movieId) {
        return schedules.stream()
                .filter(schedule -> movieId.equals(schedule.getMovieId()))
                .collect(Collectors.toList());
    }

    @Override
    public List<Schedule> findByDateRange(LocalDateTime startDate, LocalDateTime endDate) {
        return schedules.stream()
                .filter(schedule -> {
                    LocalDateTime showTime = schedule.getShowTime();
                    return !showTime.isBefore(startDate) && !showTime.isAfter(endDate);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Schedule> findByCinemaHall(String cinemaHall) {
        return schedules.stream()
                .filter(schedule -> cinemaHall.equals(schedule.getHallId()))
                .collect(Collectors.toList());
    }

    @Override
    public boolean update(Schedule schedule) {
        if (schedule == null) {
            return false;
        }
        
        for (int i = 0; i < schedules.size(); i++) {
            if (schedule.getScheduleId().equals(schedules.get(i).getScheduleId())) {
                schedules.set(i, schedule);
                saveSchedules();
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean deleteById(String scheduleId) {
        boolean removed = schedules.removeIf(schedule -> scheduleId.equals(schedule.getScheduleId()));
        if (removed) {
            saveSchedules();
        }
        return removed;
    }

    @Override
    public boolean existsById(String scheduleId) {
        return schedules.stream()
                .anyMatch(schedule -> scheduleId.equals(schedule.getScheduleId()));
    }

    @Override
    public boolean hasTimeConflict(String cinemaHall, LocalDateTime showTime, int duration) {
        LocalDateTime endTime = showTime.plusMinutes(duration);
        
        return schedules.stream()
                .filter(schedule -> cinemaHall.equals(schedule.getHallId()))
                .anyMatch(schedule -> {
                    LocalDateTime existingStart = schedule.getShowTime();
                    LocalDateTime existingEnd = existingStart.plusMinutes(120); // 假设电影时长为120分钟
                    
                    // 检查时间重叠
                    return !(endTime.isBefore(existingStart) || showTime.isAfter(existingEnd));
                });
    }
}